/*
 * Copyright (c) 2015. 石头哥哥
 */

package com.comom.manager.kit.oss;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.DateUtil;
import com.aliyun.oss.model.*;
import com.comom.manager.kit.PriorityThreadFactory;
import com.comom.manager.kit.wxpay.common.Configure;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.*;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 石头哥哥
 *         </P>
 *         Date:   2015/7/22
 *         </P>
 *         Time:   23:55
 *         </P>
 *         Package: mengchongdoc
 *         </P>
 *         <p/>
 *         注解：  oss 操作 接口
 */
@Service
public class OssService {


    /**
     * oss 操作句柄
     */
    private OSSClient ossClient;


    /**
     * oss 交互处理线程池
     */
    private static final ExecutorService ossthreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()
            , new PriorityThreadFactory("@+oss处理线程+@", Thread.NORM_PRIORITY));


    /**
     * 初始化oss 服务
     */
    @SuppressWarnings({"RedundantStringToString", "ConstantConditions"})
    @PostConstruct
    private void initOssService() throws ConfigurationException {

        String osName = System.getProperties().getProperty("os.name"); //操作系统名称
        //init oss config
        String configFileName;
        if (osName.contains("Mac")) {
            //mac os
            configFileName = this.getClass().getClassLoader().getResource("")
                    .getPath().toString().replace("WEB-INF/classes/", "WEB-INF/res/oss.properties");
        } else {
            configFileName = this.getClass().getClassLoader().getResource("")
                    .getPath().toString().replace("classes/", "res/oss.properties");
        }

        PropertiesConfiguration ossconfig = new PropertiesConfiguration(configFileName);

        OssConstants.endpoint = ossconfig.getString("endpoint");
        OssConstants.accessKeyId = ossconfig.getString("accessKeyId");
        OssConstants.secretAccessKey = ossconfig.getString("secretAccessKey");

        /**
         * oss  bucket name
         */
        OssConstants.bucketName = ossconfig.getString("bucketName");

        /**
         * oss  对外提供访问接口 图片服务 uri
         */
        OssConstants.url = ossconfig.getString("url");

        /**
         * 支付宝回调地址
         */
        OssConstants.ailipay_notify_url = ossconfig.getString("ailipay_notify_url");

        /**
         * 支付宝退款异步通知地址
         */
        OssConstants.alipay_refund_notify_url = ossconfig.getString("alipay_refund_notify_url");
        /**
         * 微信支付 异步回调地址
         */
        OssConstants.weixin_notify_url = ossconfig.getString("weixin_notify_url");

        Configure.notify_url = OssConstants.weixin_notify_url;

        /**
         * 当前服务器地址
         */
        OssConstants.server_url = OssConstants.ailipay_notify_url.replace("/aliPayNotify", "");

        /**
         * 分页 每一页显示的数据大小
         */

        OssConstants.pagesize = ossconfig.getInt("pagesize");


        //init oss client
        ossClient = new OSSClient(OssConstants.endpoint, OssConstants.accessKeyId, OssConstants.secretAccessKey);

        //create bucket  ---  in consle
        createBucket(OssConstants.bucketName, CannedAccessControlList.PublicRead);

    }


    /**
     * shut down thread pool  and oss client
     */
    @PreDestroy
    private void destroyThreadPool() {
        ossthreadPool.shutdownNow();
    }

    /**
     * 创建bucket
     *
     * @param bucketName
     */
    public void createBucket(final String bucketName) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (!ossClient.doesBucketExist(bucketName)) {
                    ossClient.createBucket(bucketName);
                }
            }
        });
    }

    /**
     * 创建bucket   指定操作权限
     *
     * @param bucketName
     * @param cannedAccessControlList CAL   控制访问权限 {@link CannedAccessControlList}
     */
    public void createBucket(final String bucketName, final CannedAccessControlList cannedAccessControlList) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (!ossClient.doesBucketExist(bucketName)) {
                    CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                    createBucketRequest.setCannedACL(cannedAccessControlList);
                    ossClient.createBucket(createBucketRequest);
                }
            }
        });
    }


    /**
     * show current buckets
     */
    public void listBuckets() {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (Bucket bucket : ossClient.listBuckets()) {
                    System.out.println(bucket.toString());
                }
            }
        });
    }

    /**
     * 删除指定的bucket
     *
     * @param bucketName
     */
    public void deleteBucket(final String bucketName) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (ossClient.doesBucketExist(bucketName)) {
                    //delete the object
                    ObjectListing objectListing = ossClient.listObjects(bucketName);
                    for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                        ossClient.deleteObject(bucketName, objectSummary.getKey());
                    }
                    //delete the bucket
                    ossClient.deleteBucket(bucketName);
                }
            }
        });
    }


    /**
     * 删除指定的 文件
     *
     * @param bucketName
     * @param key        如：file.txt  ; img/me.png;
     */
    public void deleteObject(final String bucketName, final String key) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                ossClient.deleteObject(bucketName, key);
            }
        });
    }


    /**
     * 创建虚拟文件夹               create
     *
     * @param bucketName
     * @param folderName
     */
    public void createfolder(final String bucketName, final String folderName) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (!ossClient.doesObjectExist(bucketName, folderName)) {
                    ObjectMetadata objectMeta = new ObjectMetadata();
                    ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
                    objectMeta.setContentLength(0);
                    try {
                        ossClient.putObject(bucketName, folderName, in, objectMeta);
                    } finally {
                        try {
                            in.close();    //close  input stream
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
    }


    /**
     * 上传文件   默认 10年过期
     *
     * @param bucketName
     * @param key           文件  img/me.png ;video/av.mp4;    本地server储存地址
     * @param contentLength
     * @param input
     */
    public void putObject(final String bucketName, final String key,
                          final int contentLength, final InputStream input) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //handle by thread pool
                    putObject(bucketName, key, contentLength, input, OssConstants.expiredTime); //
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 上传文件
     *
     * @param bucketName     bucket name
     * @param key            上传文件名
     * @param contentLength  上传文件长度
     * @param inputStream    文件流
     * @param expirationTime 文件超时
     */
    private void putObject(final String bucketName, final String key, final int contentLength
            , final InputStream inputStream, final int expirationTime) throws IOException {
        ObjectMetadata meta = new ObjectMetadata();
        meta.setContentLength(contentLength); //设置文件长度
        Date expire = new Date(new Date().getTime() + expirationTime * 31536000000L);
        meta.setExpirationTime(expire);  //设置超时
        ossClient.putObject(bucketName, key, inputStream, meta);
        // input had closed
    }


    /**
     * 注意处理文件生命周期
     * http://docs.aliyun.com/?spm=5176.775974648.2.5.mPMkyL#/pub/oss/sdk/java-sdk&object
     * 文件上传
     *
     * @param bucketName
     * @param key
     * @param filePath
     */
    public void putObjectLocal(final String bucketName, final String key, final String filePath) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                putObjectLocal(bucketName, key, filePath, OssConstants.expiredTime); //
            }
        });
    }

    /**
     * 注意处理文件生命周期
     * http://docs.aliyun.com/?spm=5176.775974648.2.5.mPMkyL#/pub/oss/sdk/java-sdk&object
     * 文件上传
     *
     * @param bucketName
     * @param key
     * @param filePath
     * @param expirationTime 设置超时间隔  单位 年
     */
    private void putObjectLocal(final String bucketName, final String key,
                                final String filePath, final int expirationTime) {
        File file = new File(filePath);
        InputStream content;
        try {
            content = new FileInputStream(file);
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentLength(file.length()); //设置文件长度
            Date expire = new Date(new Date().getTime() + expirationTime * 31536000000L);   //1年（365天）=31536000000L毫秒
            meta.setExpirationTime(expire);  //设置超时
            ossClient.putObject(bucketName, key, content, meta);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定的object  并写入指定的路径
     *
     * @param bucketName
     * @param key
     * @param filepath
     */
    public void getObject(final String bucketName, final String key, final String filepath) {
        ossthreadPool.execute(new Runnable() {
            @Override
            public void run() {
                OSSObject object = ossClient.getObject(bucketName, key);
                InputStream objectContent = object.getObjectContent();
                try {
                    FileUtils.copyInputStreamToFile(objectContent, new File(filepath));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 获取指定文件输入流
     * 注意需要关闭文件
     *
     * @param bucketName
     * @param key
     * @return
     * @throws IOException
     */
    public InputStream getObjectInputStream(final String bucketName, final String key) throws IOException {
        OSSObject object = ossClient.getObject(bucketName, key);
        return object.getObjectContent();
    }


    public static void main(String[] ars) {
        boolean s = new Date().getTime() == new Date().getTime();
        Date expire = new Date(new Date().getTime() + 1825 * 86400000L);   //默认5年过期
        System.out.println(DateUtil.formatRfc822Date(expire));
    }

}
